#ifndef MOTIONDETECT_H
#define MOTIONDETECT_H

#include <vector>
#include <opencv2/core/core.hpp>
#include <opencv2/video/video.hpp>
#include <opencv2/features2d/features2d.hpp>
#include "timestamp.h"
class MotionDetect
{
public:
    MotionDetect();
    ~MotionDetect();
    bool getDisplacement(std::vector<cv::Point2f> bg_pre, std::vector<cv::Point2f> bg_cur,
                         std::vector<cv::Point2f> fg_pre, std::vector<cv::Point2f> fg_cur,
                         cv::Mat &bg_mat, cv::Mat &fg_mat);
    bool getBackgroundTransform(cv::Mat pre, cv::Rect fg_area, cv::Mat cur, cv::Mat &warp_mat,
                                bool use_old_keypoints = true, int num = 6);
    bool findInterestArea(cv::Mat pre, cv::Rect area, cv::Mat cur, cv::Mat &found,
                          bool use_old_keypoints = true, int num = 6);
    bool spreadInterestPoint(cv::Mat pre, TimeStamp pre_ts, cv::Mat cur, TimeStamp cur_ts, cv::Rect &area, cv::Point2f &interest, std::vector<cv::Point2f> &spreaded, bool use_old = true);
    bool trackObject(cv::Mat pre, TimeStamp pre_ts, cv::Mat cur, TimeStamp cur_ts, cv::Rect &area, cv::Point2f &kernel, std::vector<cv::Point2f> &obj_points);
    bool detectMovingObjects(cv::Mat pre, cv::Mat cur, cv::Rect area, cv::Mat &mask,
                             int erode_iteration = 2, int dilate_iteration = 3);
    bool shakeAdjust(cv::Mat pre, cv::Mat cur, cv::Rect area, cv::Rect obj_area, cv::Mat &mask);
    bool findObject(cv::Mat pre, cv::Rect object, cv::Mat &cur, cv::Rect &found, bool use_old = true);
    bool findObjects(cv::Mat pre, std::vector<cv::Rect> objects,
                     cv::Mat cur, std::vector<cv::Rect> &found,
                     std::vector<unsigned char> &status);
    bool matchObject(cv::Mat pre, cv::Rect object, cv::Mat &cur, cv::Rect &found, bool use_old = true);
    bool matchColor(cv::Mat pre, cv::Rect object, cv::Mat &cur, cv::RotatedRect found);
    bool temperalDifferencing(cv::Mat pre, cv::Mat cur, cv::Mat next, cv::Rect area, cv::Mat &mask, int threshold = 10, int erode_iteration = 1, int dilate_iteration = 1);
    bool getKeyPointsSURF(cv::Mat img, cv::Mat mask, std::vector<cv::KeyPoint> &keypoints);
    bool getKeyPointsSIFT(cv::Mat img, cv::Mat mask, std::vector<cv::KeyPoint> &keypoints);
    bool detectOpticalFlow(cv::Mat pre, cv::Mat cur, cv::Rect area, cv::Mat &mask, float threshold, int erode_iteration = 1, int dilate_iteration = 1);
    int m_find_cost;
    int m_detect_cost;
    int m_transform_cost;
    int m_match_cost;
    int m_disp_cost;
    int m_keypoints_cost;
    int m_calc_cost;
    int m_track_cost;
    int m_adjust_cost;
    cv::BackgroundSubtractorMOG2 m_bg_model;
    static inline bool testRect(cv::Rect area, cv::Point2f point){
        return (point.x >= area.x && point.x <= area.x + area.width)
                && (point.y >= area.y && point.y <= area.y + area.height);
    }
private:
    std::vector<cv::KeyPoint> m_old_keypoints;
    std::vector<cv::Point2f> m_old_points;
    cv::Mat m_old_descriptors;
    cv::Mat m_old_flow;
    double m_velo_x;
    double m_velo_y;
    TimeStamp m_old_ts;

};

#endif // MOTIONDETECT_H
